package com.sky.service.impl;

import com.sky.entity.Top;
import com.sky.mapper.ReportMapper;
import com.sky.service.ReportService;
import com.sky.vo.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;

@Service
public class ReportServiceImpl implements ReportService {

    private static final Logger log = LoggerFactory.getLogger(ReportServiceImpl.class);
    @Autowired
    ReportMapper reportMapper;
    /**
     * 统计时间范围内的营业额
     * @param begin
     * @param end
     * @return
     */
    @Override
    public TurnoverReportVO getTurnoverStatistics(LocalDate begin, LocalDate end) {

        //开始start到end日期的集合
        List<LocalDate> dateList = getTimeFrame(begin, end);

        String list1 = StringUtils.join(dateList, ",");//日期使用字符串进行封装，StringUtil.join将集合和分隔符拼成字符串
        //根据日期查询当天的营业额
        List<String> turnoverList = new ArrayList<>();
        for (LocalDate date : dateList) {
            //date只有年月日，而orderTime包含时分秒
            //startTime设置到当天的0时0分0秒
            //endTime设置到当天的23时59分59秒
            //这里使用常量来设定时分秒
            LocalDateTime beginTime = LocalDateTime.of(date, LocalTime.MIN);
            LocalDateTime endTime = LocalDateTime.of(date, LocalTime.MAX);
            Double turnover = reportMapper.getTurnoverByTime(beginTime,endTime);

            if(turnover == null) {//判断为空或null
                turnoverList.add(String.valueOf(0));
            }else {
                turnoverList.add(String.valueOf(turnover));
            }

        }
        log.info("turnoverList{}", turnoverList);
        String list2 = StringUtils.join(turnoverList, ",");

        //使用VO进行封装
        TurnoverReportVO turnoverReport = new TurnoverReportVO();
        turnoverReport.setDateList(list1);
        turnoverReport.setTurnoverList(list2);
        log.info("营业额统计：DateList：{} TurnoverList：{}", list1, list2);
        return turnoverReport;
    }

    /**
     * 统计订单数据
     * @param begin
     * @param end
     * @return
     */
    @Override
    public UserReportVO getUserReport(LocalDate begin, LocalDate end) {
        //开始start到end日期的集合
        List<LocalDate> dateList = getTimeFrame(begin, end);

        String list1 = StringUtils.join(dateList, ",");//日期使用字符串进行封装，StringUtil.join将集合和分隔符拼成字符串

        //获取时间范围内的用户数量
        List<String> newUserList = new ArrayList<>();
        List<String> userNumberList = new ArrayList<>();
        for (LocalDate date : dateList) {
            LocalDateTime beginTime = LocalDateTime.of(date, LocalTime.MIN);
            LocalDateTime endTime = LocalDateTime.of(date, LocalTime.MAX);

            //获取新增用户
            Integer newUser = reportMapper.getUserByTime(beginTime,endTime);
            if(newUser == null) {
                newUserList.add(String.valueOf(0));
            }else {
                newUserList.add(String.valueOf(newUser));
            }

            //获取使用用户数量
             Integer userNumber = reportMapper.getAllUser(beginTime,endTime);
             if(userNumber==null ){
                 userNumberList.add(String.valueOf(0));
             }else {
                 userNumberList.add(String.valueOf(userNumber));
             }

        }
        log.info("新用户数量统计：{}，用户使用统计：{}",newUserList,userNumberList);
        String list2 = StringUtils.join(newUserList, ",");
        String list3 = StringUtils.join(userNumberList,",");

        //封装
        UserReportVO userReport = new UserReportVO();
        userReport.setDateList(list1);
        userReport.setNewUserList(list2);
        userReport.setTotalUserList(list3);
        return userReport;
    }

    /**
     *订单统计数据
     * @param begin
     * @param end
     * @return
     */
    @Override
    public OrderReportVO getOrderPort(LocalDate begin, LocalDate end) {
        List<LocalDate> dateList = getTimeFrame(begin,end);
        String list1 = StringUtils.join(dateList,",");

        Integer totalOrderCount = reportMapper.getTotalOrderCount();//订单总数
        Integer validOrderCount = reportMapper.getValidOrderCount();//有效订单数
        Double orderCompletionRate = (double)validOrderCount/totalOrderCount;//订单完成率


        List<String> orderCountList = new ArrayList<>();//订单数集合
        List<String> validOrderCountList = new ArrayList<>();//有效订单数集合
        for (LocalDate date : dateList) {
            LocalDateTime beginTime = LocalDateTime.of(date, LocalTime.MIN);
            LocalDateTime endTime = LocalDateTime.of(date, LocalTime.MAX);
            //查询每日订单数量
            Integer orderCount = reportMapper.getOrderCount(beginTime,endTime);
            if(orderCount == null){
                orderCountList.add(String.valueOf(0));
            }else {
                orderCountList.add(String.valueOf(orderCount));
            }
            //查询有效数量
            Integer validOrder = reportMapper.getValidOrder(beginTime,endTime);
            if(validOrder == null ){
                validOrderCountList.add(String.valueOf(0));
            }else {
                validOrderCountList.add(String.valueOf(validOrder));
            }
        }
        String list2 = StringUtils.join(orderCountList,",");
        String list3 = StringUtils.join(validOrderCountList,",");

        //封装
        return new OrderReportVO(list1,list2,list3,totalOrderCount,validOrderCount,orderCompletionRate);
    }

    //销量排行
    @Override
    public SalesTop10ReportVO getTop(LocalDate begin, LocalDate end) {
        //获取销量排行
        LocalDateTime beginTime = LocalDateTime.of(begin, LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(end, LocalTime.MAX);
        List<Top> toplist  = reportMapper.getTop(beginTime,endTime);

        //使用stream流获取其中一个属性
        List<String> nameList = toplist.stream().map(Top::getName).toList();
        List<String> numberList = toplist.stream().map(Top:: getNumber).toList();
        //转换成字符串
        String list2 = StringUtils.join(nameList,",");
        String list3 = StringUtils.join(numberList,",");
        //封装

        SalesTop10ReportVO salesTop10Report = new SalesTop10ReportVO();
        salesTop10Report.setNameList(list2);
        salesTop10Report.setNumberList(list3);

        log.info("销售数量排行{}",salesTop10Report);
        return salesTop10Report;
    }

    //工作台查询今日运营数据
    @Override
    public BusinessDataVO getBusinessData() {
        //当天时间的开始和结束
        LocalDate time = LocalDate.now();
        LocalDateTime begin = LocalDateTime.of(time, LocalTime.MIN);
        LocalDateTime end = LocalDateTime.of(time, LocalTime.MAX);
        //当天新用户
        Integer  newUsers = reportMapper.getUserByTime(begin,end);

        //当天全部订单数
        int orderCount= reportMapper.getOrderCount(begin, end);
        //当天已完成订单数(有效订单)
        Integer validOrder = reportMapper.getValidOrder(begin, end);
        //订单完成率
        Double orderCompletionRate = (double)validOrder/orderCount;

        //当天营业额
        Double turnover = reportMapper.getTurnoverByTime(begin,end);
        if(turnover == null){
            turnover = 0.0;
        }

        //当天用户数量
        Integer users = Integer.valueOf(reportMapper.getAllUser(begin,end));
        //平均客单价
        Double unitPrice = turnover/users;

        //有效订单数
        Integer validOrderCount = reportMapper.getValidOrder(begin,end);

        //封装
        BusinessDataVO businessDataVO = new BusinessDataVO();
        businessDataVO.setNewUsers(newUsers);
        businessDataVO.setTurnover(turnover);
        businessDataVO.setUnitPrice(unitPrice);
        businessDataVO.setValidOrderCount(validOrderCount);
        businessDataVO.setOrderCompletionRate(orderCompletionRate);
        return businessDataVO;
    }

    //导出excel表格
    @Override
    public void getExcel(HttpServletResponse response) throws IOException {
        //输入流获取文件
        InputStream in = this.getClass().getClassLoader().getResourceAsStream("template/外卖导出数据信息.xlsx");
        //获取基于输入流获取文件
        XSSFWorkbook excel = new XSSFWorkbook(in);
        XSSFSheet sheet = excel.getSheet("外卖导出数据信息");//名字为 外卖导出数据信息 的信息页

        XSSFRow row = sheet.getRow(3);//第四行
        //近三十天的数据
        LocalDate end = LocalDate.now().plusDays(-1);//最后是昨天
        LocalDate begin = end.plusDays(-29);//第一天
        //填充时间
        row.getCell(0).setCellValue("时间："+begin+" ～ "+end);

        //获取营业额
        LocalDateTime beginTime = LocalDateTime.of(begin, LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(end, LocalTime.MAX);
        Double turnover = reportMapper.getTurnoverByTime(beginTime, endTime);
        if(turnover == null){
            turnover = 0.0;
        }//填充营业额
        row = sheet.getRow(5);//第六行
        //模板已经创建过了，就不需要创建了
        row.getCell(1).setCellValue("￥"+String.format("%.2f", turnover));
        //有效订单数
        Integer validOrder = reportMapper.getValidOrder(beginTime, endTime);
        //订单总数
        Integer orderCount = reportMapper.getOrderCount(beginTime, endTime);
        double orderCompletionRate = (double)validOrder/orderCount;
        row.getCell(3).setCellValue(String.format("%.2f",orderCompletionRate)+"%");//订单完成率
        row.getCell(5).setCellValue(reportMapper.getUserByTime(beginTime,endTime));

        row = sheet.getRow(6);
        row.getCell(1).setCellValue(validOrder);//有效订单数

        Integer users = reportMapper.getAllUser(beginTime, endTime);
        if(users == null||users == 0){
            row.getCell(3).setCellValue("￥0.00");
        }else {
            row.getCell(3).setCellValue("￥"+String.format("%.2f",(double)turnover/users) );//平均客单价
        }
        //明细数据
        //获取三十天的日期集合
        List<LocalDate> dateList = getTimeFrame(begin, end);
        for(int i=9;i<=38;i++){
            row = sheet.getRow(i);//确定行数
            LocalDate dataDate = dateList.get(i-9);//确定日期
            LocalDateTime dateBegin = LocalDateTime.of(dataDate, LocalTime.MIN);
            LocalDateTime dateEnd = LocalDateTime.of(dataDate, LocalTime.MAX);
            row.getCell(0).setCellValue(dataDate.toString());//日期
            Double turnoverByTime = reportMapper.getTurnoverByTime(dateBegin, dateEnd);
            if(turnoverByTime == null){
                turnoverByTime = 0.00;
            }
            row.getCell(1).setCellValue("￥"+String.format("%.2f", turnoverByTime));//营业额
            Integer dateValidOrder = reportMapper.getValidOrder(dateBegin, dateEnd);
            Integer dateOrderCount = reportMapper.getOrderCount(dateBegin, dateEnd);
            row.getCell(2).setCellValue(dateValidOrder);//有效订单
            if(dateValidOrder==0||dateOrderCount==0){
                row.getCell(3).setCellValue("0.00%");
            }else {
                row.getCell(3).setCellValue(String.format("%.2f",((double)dateValidOrder/dateOrderCount*100))+"%");//订单完成率
            }
            Integer dateUsers = reportMapper.getAllUser(dateBegin, dateEnd);
            if(dateUsers == null||dateUsers == 0){
                row.getCell(4).setCellValue("￥0.00");
            }else {
                row.getCell(4).setCellValue("￥"+String.format("%.2f", (double) turnoverByTime/dateUsers));//平均客单价
            }
            row.getCell(5).setCellValue(reportMapper.getUserByTime(dateBegin,dateEnd));//新增用户数
        }
        // 写出到响应输出流
        ServletOutputStream out = response.getOutputStream();
        excel.write(out);

        FileOutputStream outFile = new FileOutputStream("E:\\JAVA\\苍穹外卖\\资料\\资料\\day01\\后端初始工程\\sky-take-out\\sky-server\\src\\main\\resources\\template\\外卖导出数据信息.xlsx");
        excel.write(outFile);
        outFile.close();
        excel.close();
        out.close();
    }

    //获取时间范围的集合
    public List<LocalDate> getTimeFrame(LocalDate begin, LocalDate end){
        //开始start到end日期的集合
        List<LocalDate> dateList = new ArrayList<>();
        dateList.add(begin);
        while (!begin.isEqual(end)) {
            begin =  begin.plusDays(1);//start往后推一天
            dateList.add(begin);
        }
        return dateList;
    }
}
